package com.njzxw.fs.commonutil.test;

import com.njzxw.fs.commonutil.bean.BaseUserBean;
import com.njzxw.fs.commonutil.bean.Common;
import com.njzxw.fs.commonutil.bean.ShowDocBean;
import com.njzxw.fs.commonutil.repository.BaseRep;
import com.njzxw.fs.commonutil.util.GsonUtil;
import com.njzxw.fs.commonutil.util.RedisUtil;
import com.njzxw.fs.commonutil.util.StringHelper;
import com.njzxw.fs.commonutil.util.UserUtil;
import com.njzxw.fs.commonutil.web.ReturnMap;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.WebApplicationContext;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import javax.servlet.http.Cookie;
import java.io.*;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import static org.testng.Assert.assertTrue;

//@SpringBootTest(classes=ServiceApiApplication.class)
@WebAppConfiguration
@Transactional
@Rollback(value = false)
public class BaseJunit extends AbstractTestNGSpringContextTests{

    // 这里注意，使用@Rule注解必须要用public  捕获所有Test执行输出
    @Autowired
    protected WebApplicationContext wac;

    @Autowired
    protected RedisUtil redisUtil;

    @Autowired
    protected Common common;

    protected MockMvc mvc;

    private static String CHECK_COOKIES_ID = "QLEGJ2K9FOIZER12YHI4PB51Q85CAEJV";

    public Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ShowDocBean showDocBean;

    @Autowired
    private UserUtil userUtil;

    /**
     * 默认登陆用户角色
     */
    public String mobileDefault = "18252028618";

    /**
     * 默认文本请求信息
     */
    private MockHttpServletRequestBuilder https;

    /**
     * 文件上传的请求信息
     */
    private MockMultipartHttpServletRequestBuilder multiparHttps;

    @BeforeMethod
    public void setUp() {
        this.mvc = webAppContextSetup(wac).build();
    }

    /**
     * 返回值必须是返回200并且是json 且为utf-8格式，json格式必须为{state:1,xxxx}格式
     *
     * @param response
     * @param state 返回的json数据需要为几才嫩满足
     * @return
     */
    public boolean checkJsonUtf8DataResult(MockHttpServletResponse response, int state) {
        return checkJsonUtf8DataResult(response, new int[]{state});
    }

    /**
     * 返回值必须是返回200并且是json 且为utf-8格式，json格式必须为{state:1,xxxx}格式
     *
     * @param response
     * @param state 返回的json数据需要为几才嫩满足
     * @return
     */
    public boolean checkJsonUtf8DataResult(MockHttpServletResponse response, int[] state) {
        //检查返回值状态是否正确
        assertTrue(response.getStatus() == 200);
        logger.debug("Content-Type:" + response.getHeader("Content-Type"));
        //检查返回值是否是utf-8并且是json数据格式参数
        assertTrue(response.getHeader("Content-Type").equals("application/json;charset=utf-8"));
        try {
            String result = getResponseValue(response);
            return checkDataState(result, state);
        } catch (Exception e) {
            logger.error("test校验格式出现错误信息：", e);
        }
        return false;
    }

    public boolean checkJsonUtf8DataResult(MockHttpServletResponse response, ReturnMap.States state) {
        return checkJsonUtf8DataResult(response, Integer.valueOf(ReturnMap.States.getValue(state)));
    }

    /**
     * 获取response返回参数
     *
     * @param response
     * @return
     */
    public String getResponseValue(MockHttpServletResponse response) {
        try {
            return response.getContentAsString();
        } catch (UnsupportedEncodingException e) {
            logger.error("test校验格式出现错误信息：", e);
        }
        return "";
    }

    /**
     * 校验输入参数值是否是带有state并且与state相同
     *
     * @param jsonData
     * @param state
     * @return
     */
    public boolean checkDataState(String jsonData, int state) {
        return checkDataState(jsonData, new int[]{state});
    }

    /**
     * 校验输入参数值是否是带有state并且与state相同
     *
     * @param jsonData
     * @param state
     * @return
     */
    public boolean checkDataState(String jsonData, int[] state) {
        logger.debug("junit返回的jsonData：" + jsonData);
        Map<String, Object> resultMap = GsonUtil.parseJsonWithGson(jsonData, Map.class);
        logger.debug("junit返回的resultMap：" + resultMap);
        //是否存在state值
        assertTrue(resultMap.containsKey("state"));
        //state值是否为state参数
//		assertTrue(StringHelper.get(resultMap, "state").equals(String.valueOf(state)));
        if (state == null || state.length == 0) {
            return false;
        }
        for (int i = 0; i < state.length; i++) {
            if (StringHelper.get(resultMap, "state").equals(String.valueOf(state[i]))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 打印出请求详细信息
     *
     * @param resultAction
     * @throws Exception
     */
    public void printReq(ResultActions resultAction) throws Exception {
        resultAction.andDo(print());
    }

    /**
     * 获取cookies
     *
     * @throws Exception
     */
    public void getCookies() throws Exception {
        if (CHECK_COOKIES_ID.equals("")) {
            MockHttpServletRequestBuilder https = MockMvcRequestBuilders.get("/login/login");
            ResultActions resultAction = mvc.perform(https);
            resultAction.andDo(MockMvcResultHandlers.print());
            MvcResult result = resultAction.andReturn();
            MockHttpServletResponse response = result.getResponse();
            String cookies = response.getCookie("CHECK_COOKIES_ID").getValue();
            System.out.println("获取的cookies:" + cookies);
            logger.debug("获取的cookies：" + cookies);
            this.CHECK_COOKIES_ID = cookies;
        }
    }

    /**
     * 设置初始cookies
     *
     * @param https
     */
    public void setCookies(MockHttpServletRequestBuilder https) throws Exception {
        if ("".equals(CHECK_COOKIES_ID)) {
            getCookies();
            if ("".equals(CHECK_COOKIES_ID)) {
                logger.error("无法设置cookises，参数值位空");
            } else {
                https.cookie(new Cookie("CHECK_COOKIES_ID", CHECK_COOKIES_ID));
            }
        } else {
            https.cookie(new Cookie("CHECK_COOKIES_ID", CHECK_COOKIES_ID));
        }
    }

//    /**
//     * 获取验证码信息
//     *
//     * @throws Exception
//     */
//    public String getCode(String type) throws Exception {
//        MockHttpServletRequestBuilder https = MockMvcRequestBuilders.get("/code/getCode");
//        setCookies(https);
//        https.param("type", type);
//        ResultActions resultAction = mvc.perform(https);
////    	resultAction.andDo(MockMvcResultHandlers.print());
//        MvcResult result = resultAction.andReturn();
//        MockHttpServletResponse response = result.getResponse();
//        String cookies = response.getCookie("CHECK_COOKIES_ID").getValue();
////        String code = cacheManagerUtil.getCache(common.getCodeCacheName(), cookies + "_" + type, String.class);
//        logger.debug("获取的code:" + code);
//        return code;
//    }

    public enum RequestType {
        POST, GET, PUT, PATCH, DELETE, OPTIONS, HEAD
    }

    /**
     * 请求参数的类型，是传递的ｊｓｏｎ还是ｍａｐ键值对
     */
    public enum RequestParamsType {
        JSON, MAP
    }

    /**
     * 参数添加列表
     */
    public class RequestParams {

        /**
         * 参数名称
         */
        private String name;
        /**
         * 参数值 只能传入String或者　List<RequestParams> 或者 List<List<RequestParams>>
         */
        private Object value;
        /**
         * 是否必填
         */
        private boolean isMust;

        /**
         * 参数说明
         */
        private String remark;

        private Object sucssVal;

        public Object getSucssVal() {
            return sucssVal;
        }

        public void setSucssVal(Object sucssVal) {
            this.sucssVal = sucssVal;
        }

        private List<Object[]> errorList = new ArrayList<>();

        private List<Object[]> getErrorList(){
            return this.errorList;
        }

        private RequestParams() {
        }

        public RequestParams addError(Object val,String msg){
            errorList.add(new Object[]{val,msg});
            return this;
        }

        /**
         *
         * @param name 参数名称
         * @param value 参数值 只能传入String或者　List<RequestParams> 或者
         * List<List<RequestParams>>
         * @param isMust 是否必填
         * @param remark 参数说明
         */
        public RequestParams(String name, Object value, boolean isMust, String remark) {
            this.name = name;
            this.value = value;
            this.isMust = isMust;
            this.remark = remark;
        }

        /**
         * 参数名称
         *
         * @return the name
         */
        public String getName() {
            return name;
        }

        /**
         * 参数名称
         *
         * @param name the name to set
         */
        public void setName(String name) {
            this.name = name;
        }

        /**
         * 参数值
         *
         * @return the value
         */
        public Object getValue() {
            return value;
        }

        /**
         * 参数值 只能传入String或者 RequestParams　List<RequestParams> 或者
         * List<List<RequestParams>>
         *
         * @param value the value to set
         */
        public void setValue(Object value) {
            this.value = value;
        }

        /**
         * 是否必填
         *
         * @return the isMust
         */
        public boolean isIsMust() {
            return isMust;
        }

        /**
         * 是否必填
         *
         * @param isMust the isMust to set
         */
        public void setIsMust(boolean isMust) {
            this.isMust = isMust;
        }

        /**
         * 参数说明
         *
         * @return the remark
         */
        public String getRemark() {
            return remark;
        }

        /**
         * 参数说明
         *
         * @param remark the remark to set
         */
        public void setRemark(String remark) {
            this.remark = remark;
        }

        @Override
        public String toString() {
            return "requestParams{" + "name=" + name + ", value=" + value + ", isMust=" + isMust + ", remark=" + remark + '}';
        }

    }

    /**
     * 模拟文件上传，需要上传的文件放入test的resource文件夹，前缀带上/
     * @param files
     * @return
     */
    public List<String> uploadFile(List<String> files){

        try{
            RequestTest requestTest = new RequestTest("文件上传接口",true,RequestType.POST,"/uploadFile");

            //设置请求参数
            List<RequestParams> params = new ArrayList<RequestParams>();

            if(files == null || files.isEmpty()){
                return new ArrayList<>();
            }

            for(int i=0;i<files.size();i++){
                String originalFileName = files.get(i).substring(files.get(i).lastIndexOf("\\")+1);
                logger.debug("==:"+files.get(i),this.getClass().getResource(files.get(i))==null);
                params.add(new RequestParams("file",new MockMultipartFile("file",originalFileName,"image/jpeg",new FileInputStream(this.getClass().getResource(files.get(i)).toURI().getPath())),true,"上传文件"));
            }
            requestTest.setParams(params);
            MockHttpServletResponse response = requestTest.executeReturnIntCode(new int[]{1});

            JSONObject jsonObject = JSONObject.fromObject(response.getContentAsString());

            JSONArray jsonArray = jsonObject.getJSONArray("data");

            List<String> fileList = new ArrayList<>();
            for(int i=0;i<jsonArray.size();i++){
                fileList.add(jsonArray.getJSONObject(i).getString("id"));
            }


            return fileList;
        }catch (Exception e){
            e.printStackTrace();
            assertTrue(false);
        }
        return new ArrayList<>();
    }

    public class RequestTest {

        private HttpHeaders httpHeaders;

        private List<RequestParams> requestParamsList;

        private Map<String, Object> paramsMap;

        private String name;

        private String uri;

        private String des;

        private RequestType requestType;

        private RequestParamsType requestParamsType;

        private boolean isJsonResult;

        private StringBuffer stringBufferError = new StringBuffer();

        /**
         * 是否是文件上传接口
         */
        private boolean isMultipart;

        private String resultStr;

        public String getToken(String oper_id){
            String token = UUID.randomUUID().toString();
            BaseUserBean baseUserBean = new BaseUserBean();
            baseUserBean.setOper_id(oper_id);
            userUtil.setBaseUserBean(baseUserBean);
            Map<String,Object> map = userUtil.getClientUser();
            redisUtil.setKey(token, JSONObject.fromObject(map).toString(),Long.valueOf(common.getSystem("LOGIN.OUT.TIME")), TimeUnit.MINUTES);
            return token;
        }

        /**
         *
         * @param name 接口标题
         */
        public RequestTest(String name) throws Exception {
            this.name = name;
            if(StringUtils.isBlank(this.uri)){
                geiUrl();
            }

        }

        /**
         *
         * @param name 接口标题
         */
        public RequestTest(String name,String url) throws Exception {
            this.name = name;
            this.uri = url;
            if(StringUtils.isBlank(this.uri)){
                geiUrl();
            }

        }

        /**
         *
         * @param name 接口标题
         */
        public RequestTest(String name,boolean isMultipart) throws Exception {
//            this.name = name;
//            this.isMultipart = isMultipart;
//            geiUrl();
            this(name,isMultipart,null);
        }

        /**
         *
         * @param name 接口标题
         */
        public RequestTest(String name,boolean isMultipart,String url) throws Exception {
            this.name = name;
            this.isMultipart = isMultipart;
            if(url == null){
                geiUrl();
            }else{
                this.requestType = RequestType.POST;
                setRequestUrl(this.requestType,url);
            }
        }

        /**
         * 进行登录操作
         *
         * @param oper_id
         */
        public void login(String oper_id){



        }

        /**
         * 拦截自动获得访问url
         *
         * @return
         */
        public void geiUrl() throws Exception {
            String uri = "";
            StackTraceElement[] temp = Thread.currentThread().getStackTrace();
            for (int i = 0; i < temp.length; i++) {
                String className = temp[i].getClassName();
                String mobthName = temp[i].getMethodName();
//                System.out.println("com.ycdc.BaseTestNg.RequestTest.geiUrl():" + temp[i].getClassName() + "--" + temp[i].getMethodName());
                if (!className.contains("BaseJunit") && className.contains("com.njzxw") && !className.contains("&")) {
                    String ysClassName = className.replace("Test", "").replace("test", "");
                    String ysMobthName = UpStr(mobthName.replace("Test", "").replace("test", ""));

                    Class c = Class.forName(ysClassName);
                    RequestMapping requestMappingClass = (RequestMapping) c.getAnnotation(RequestMapping.class);
                    if (requestMappingClass != null) {
//                        System.out.println("com.ycdc.BaseTestNg.RequestTest.geiUrl()2:" + (requestMappingClass.name()));
                        uri += requestMappingClass.value()[0];
                    }
                    Method[] methods = c.getMethods();
                    for(int j=0;j<methods.length;j++){
//                        System.out.println("com.ycdc.BaseTestNg.RequestTest.geiUrl()======:"+methods[j].getName());
                        if(methods[j].getName().equals(ysMobthName)){
                            RequestMapping requestMappingMethod = methods[j].getAnnotation(RequestMapping.class);
                            if (requestMappingMethod != null) {
                                uri += requestMappingMethod.value()[0];
                                this.requestType = RequestType.POST;
                            }else {
                                PostMapping postMapping = methods[j].getAnnotation(PostMapping.class);
                                if(postMapping != null ){
                                    uri += postMapping.value()[0];
                                    this.requestType = RequestType.POST;
                                }else {
                                    GetMapping getMapping = methods[j].getAnnotation(GetMapping.class);
                                    if(getMapping != null ){
                                        uri += getMapping.value()[0];
                                        this.requestType = RequestType.GET;
                                    }
                                }
                            }
                        }
                    }
//                    System.out.println("com.ycdc.BaseTestNg.RequestTest.geiUrl()---:" + className + "--" + mobthName + "--" + ysClassName + "--" + ysMobthName);
                    break;
                }
            }
//            System.out.println("com.ycdc.BaseTestNg.RequestTest.geiUrl()---url:" + uri);
            if(!uri.startsWith("/")){
                uri = "/"+uri;
            }
            if(this.requestType == null){
                logger.error("未找到对应的url链接");
                assertTrue(false);
            }else{
                setRequestUrl(this.requestType, uri);
            }

        }

        /**
         * 首字母大小
         *
         * @param str
         * @return
         */
        private String UpStr(String str) {
            return str.replaceFirst(str.substring(0, 1), str.substring(0, 1).toLowerCase());
        }

        public RequestTest(String name, RequestType requestType, String uri) throws Exception {
            this(name);
            this.setRequestUrl(requestType, uri);
        }

        public RequestTest(String name,boolean isMultipart ,RequestType requestType, String uri) throws Exception {
            this(name,uri);
            this.isMultipart = isMultipart;
            this.setRequestUrl(requestType, uri);
        }

        /**
         *
         * @param requestType
         * @param uri
         * @param params map 键值对传入
         * @throws Exception
         */
        @Deprecated
        public RequestTest(String name, RequestType requestType, String uri, Map<String, String> params) throws Exception {
            this(name, requestType, uri);
            this.setParams(params);
        }

        public RequestTest(String name, RequestType requestType, String uri, List<RequestParams> params) throws Exception {
            this(name, requestType, uri);
            this.setParams(params);
        }

        /**
         *
         * @param requestType
         * @param uri
         * @param params map 键值对传入
         * @param requestParamsType
         * @throws Exception
         */
        @Deprecated
        public RequestTest(String name, RequestType requestType, String uri, Map<String, String> params, RequestParamsType requestParamsType) throws Exception {
            this(name, requestType, uri);
            if (RequestParamsType.JSON == requestParamsType) {
                this.setJsonParams(params);
            } else {
                this.setParams(params);
            }
        }

        public RequestTest(String name, RequestType requestType, String uri, List<RequestParams> params, RequestParamsType requestParamsType) throws Exception {
            this(name, requestType, uri);
            if (RequestParamsType.JSON == requestParamsType) {
                this.setJsonParams(params);
            } else {
                this.setParams(params);
            }
        }

        /**
         * 设置请求方法
         *
         * @param requestType
         * @param uri
         */
        public void setRequestUrl(RequestType requestType, String uri) throws Exception {

            if(this.isMultipart){
                multiparHttps = MockMvcRequestBuilders.multipart(uri);
                this.uri = uri;
                this.requestType = requestType;
                getCookies();
                return;
            }

            switch (requestType) {
                case POST:
                    https = MockMvcRequestBuilders.post(uri);
                    break;
                case GET:
                    https = MockMvcRequestBuilders.get(uri);
                    break;
                case PUT:
                    https = MockMvcRequestBuilders.put(uri);
                    break;
                case PATCH:
                    https = MockMvcRequestBuilders.patch(uri);
                    break;
                case DELETE:
                    https = MockMvcRequestBuilders.delete(uri);
                    break;
                case OPTIONS:
                    https = MockMvcRequestBuilders.options(uri);
                    break;
                case HEAD:
                    https = MockMvcRequestBuilders.head(uri);
                    break;
            }
            this.uri = uri;
            this.requestType = requestType;
            getCookies();

        }

        /**
         * 设置请求参数信息
         */
        @Deprecated
        public void setParams(Map<String, String> params) {
            if (params != null && !params.isEmpty()) {
                Set<String> set = params.keySet();
                Iterator<String> it = set.iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    String value = params.get(key);
                    https.param(key, value);
                }
            }
            this.requestParamsType = RequestParamsType.MAP;
        }

        /**
         * 设置请求参数信息
         *
         * @param requestParamsList
         */
        public void setParams(List<RequestParams> requestParamsList) {
            this.requestParamsList = requestParamsList;

            if (requestParamsList != null) {
                Map<String, Object> map = new HashMap<String, Object>();
                //转换成设置到参数中
                for (RequestParams requestParams : requestParamsList) {
                    map.put(requestParams.getName(), String.valueOf(requestParams.getValue()));

                    if(this.isMultipart){
                        Object objValue = requestParams.getValue();
                        if(objValue instanceof MockMultipartFile){
                            multiparHttps.file((MockMultipartFile)objValue);
                        }
                        multiparHttps.param(requestParams.getName(), String.valueOf(requestParams.getValue()));
                    }else{
                        https.param(requestParams.getName(), String.valueOf(requestParams.getValue()));
                    }
                }
                paramsMap = map;
            }
            this.requestParamsType = RequestParamsType.MAP;
        }

        public void setCookies() {
            if ("".equals(CHECK_COOKIES_ID)) {
                logger.error("无法设置cookises，参数值位空");
            } else {
                if(this.isMultipart){
                    multiparHttps.cookie(new Cookie("CHECK_COOKIES_ID", CHECK_COOKIES_ID));
                }else{
                    https.cookie(new Cookie("CHECK_COOKIES_ID", CHECK_COOKIES_ID));
                }

            }
        }

        /**
         * 设置头文件信息
         *
         * @param key
         * @param value
         */
        public void setHeads(String key, String value) {
            if (httpHeaders == null) {
                httpHeaders = new HttpHeaders();
            }
            httpHeaders.set(key, value);
        }

        /**
         * 设置cookies操作
         *
         * @param key
         * @param value
         */
        public void setAnyCookies(String key, String value) {
            if(this.isMultipart){
                multiparHttps.cookie(new Cookie(key, value));
            }else{
                https.cookie(new Cookie(key, value));
            }
        }

        /**
         * 传递流的形式数据格式，如json键值对
         *
         * @param params
         */
        @Deprecated
        public void setJsonParams(Map<String, String> params) {
            if (params != null && !params.isEmpty()) {
                https.content(JSONObject.fromObject(params).toString());
            }
            this.requestParamsType = RequestParamsType.JSON;
        }

        /**
         * 设置请求参数信息
         *
         * @param requestParamsList
         */
        public void setJsonParams(List<RequestParams> requestParamsList) {
            this.requestParamsList = requestParamsList;
            this.requestParamsType = RequestParamsType.JSON;
            if (requestParamsList != null) {
                Map<String, Object> params = getParamsMap(requestParamsList);
                paramsMap = params;
                https.content(JSONObject.fromObject(paramsMap).toString());
            }
            setHeads("Content-Type","application/json:charset=UTF-8");
            this.httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        }

        /**
         * 获取转换后的map参数值
         *
         * @param requestParamsList
         * @return
         */
        public Map<String, Object> getParamsMap(List<RequestParams> requestParamsList) {
            if (requestParamsList != null) {
                Map<String, Object> params = new HashMap<String, Object>();
                //转换成设置到参数中
                for (RequestParams requestParams : requestParamsList) {
                    String key = requestParams.getName();
                    Object value = requestParams.getValue();
                    if (value instanceof String) {
                        params.put(key, String.valueOf(value));
                    }else if (value instanceof Integer) {
                        params.put(key, Integer.valueOf(String.valueOf(value)));
                    } else if ((value instanceof ArrayList)) {
                        ArrayList<String> list = (ArrayList<String>) value;
                        params.put(key, JSONArray.fromObject(list));
                    } else if ((value instanceof List)) {
                        List<?> lists = (List<?>)value;

                        for(Object params_ :lists){
                            if(params_ instanceof RequestParams){
                                try {
                                    List<RequestParams> list = (List<RequestParams>) value;
                                    params.put(key, JSONObject.fromObject(getParamsMap(list)).toString());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    try {
                                        List<Map<String, Object>> paramsList = new ArrayList<Map<String, Object>>();
                                        List<ArrayList<RequestParams>> list = (List<ArrayList<RequestParams>>) value;
                                        for (List<RequestParams> param : list) {
                                            paramsList.add(getParamsMap(param));
                                        }
                                        params.put(key, JSONArray.fromObject(paramsList));
                                    } catch (Exception e1) {
                                        e1.printStackTrace();
                                        logger.warn("参数类型转换出错:", e1);
                                    }
                                }
                            }else if(params_ instanceof String){
                                params.put(key, JSONArray.fromObject((List<String>)value));
                            }else if(params_ instanceof Integer){
                                params.put(key, JSONArray.fromObject((List<Integer>)value));
                            }else if(params_ instanceof Map){
                                params.put(key, JSONArray.fromObject((List<Map<String,Object>>)value));
                            }
                        }


                    } else {
                        if(value != null){
                            logger.error("未知的参数值"+value.getClass().getSimpleName());
                            assertTrue(false);
                        }
                    }
                }
                return params;
            }
            return new HashMap<String, Object>();
        }

        /**
         * 执行返回信息是否是满足条件的，满足其中一个即可通过
         *
         * @param resultState
         * @return MockHttpServletResponse
         * @throws Exception
         */
        public MockHttpServletResponse executeReturnIntCode(int[] resultState) throws Exception {
            setCookies();
            logger.debug(this.uri + "请求参数：" + paramsMap.toString());
            ResultActions resultAction = null;

            if(httpHeaders == null){
                setHeads("1","1");
            }

            if(this.isMultipart){
                multiparHttps.headers(httpHeaders);
                resultAction = mvc.perform(multiparHttps);
            }else{
//                System.out.println("https:==="+(httpHeaders == null));
                https.headers(httpHeaders);
                resultAction = mvc.perform(https);
            }

            resultAction.andDo(MockMvcResultHandlers.print());
            MvcResult result = resultAction.andReturn();
            MockHttpServletResponse response = result.getResponse();
            assertTrue(checkJsonUtf8DataResult(response, resultState));
            resultStr = response.getContentAsString();
            isJsonResult = true;

            //捕获所有输出
//            assertThat(capture.toString(), Matchers.containsString(this.name));

            //进行插入对应的文档中
            return response;
        }

        public MockHttpServletResponse execute() throws Exception{

            isJsonResult = false;

            setCookies();

            logger.debug("请求参数："+paramsMap.toString());
            logger.debug("请求参数："+requestParamsList.toString());

            for(int i=0;i<this.requestParamsList.size();i++){

                List<RequestParams> listparams = new ArrayList<>();
                listparams.addAll(this.requestParamsList);

                listparams.get(i).setSucssVal(listparams.get(i).getValue());
                List<Object[]> error_list = listparams.get(i).getErrorList();

                if(error_list != null){
                    if(stringBufferError.length() == 0){
                        stringBufferError.append(" **错误请求与返回示例**  \n").append(" \n").append("```   \n");
                    }
                    for(int j=0;j<error_list.size();j++){

                        Object[] obj = error_list.get(j);
                        listparams.get(i).setValue(obj[0]);

                        if(requestParamsType == RequestParamsType.JSON){
                            this.setJsonParamsAgin(listparams);
                        }else{
                            this.setParamsAgin(listparams);
                        }

                        MockHttpServletResponse response = this.executeReturnMsg(String.valueOf(obj[1]));

                        String result = getResponseValue(response);

                        stringBufferError.append("示例"+i+""+j+"："+String.valueOf(obj[1])).append(" \n");
                        stringBufferError.append("  请求参数：\n");
                        changeJson(JSONObject.fromObject(paramsMap),stringBufferError,0);
                        int cnt = stringBufferError.lastIndexOf(",");
                        stringBufferError.delete(cnt,cnt+1).append("  返回示例：\n");
                        changeJson(JSONObject.fromObject(result), stringBufferError, 0);
                        cnt = stringBufferError.lastIndexOf(",");
                        stringBufferError.delete(cnt,cnt+1).append(" \n");

                    }

                }

                for(int j=0;j<this.requestParamsList.size();j++){
                    if(this.requestParamsList.get(j).getSucssVal() != null){
                        this.requestParamsList.get(j).setValue(this.requestParamsList.get(j).getSucssVal());
                    }
                }

            }
            if(stringBufferError.length() != 0){
                stringBufferError.append("``` ").append(" \n");
            }
            logger.debug("返回值-----："+stringBufferError);
            if(requestParamsType == RequestParamsType.JSON){
                this.setJsonParams(this.requestParamsList);
            }else{
                this.setParams(this.requestParamsList);
            }

            return executeReturnIntCode(new int[]{Integer.valueOf(ReturnMap.States.getValue(ReturnMap.States.SUCCEE))});

        }

        private void setJsonParamsAgin(List<RequestParams> requestParamsList){
            this.requestParamsType = RequestParamsType.JSON;
            if(requestParamsList != null){
                Map<String,Object> params = getParamsMap(requestParamsList);
                paramsMap = params;
                https.content(JSONObject.fromObject(paramsMap).toString());
            }

            setHeads("Content-Type","application/json:charset=UTF-8");
            this.httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        }

        private void setParamsAgin(List<RequestParams> requestParamsList){

            if(requestParamsList != null){

                Map<String,Object> map = new HashMap<>();
                for(RequestParams requestParams:requestParamsList){

                    map.put(requestParams.getName(),String.valueOf(requestParams.getValue()));

                    if(this.isMultipart){
                        Object objValue = requestParams.getValue();
                        if(objValue instanceof MockMultipartFile){
                            multiparHttps.file((MockMultipartFile)objValue);
                        }
                        multiparHttps.param(requestParams.getName(),String.valueOf(requestParams.getValue()));
                    }else{
                        https.param(requestParams.getName(),String.valueOf(requestParams.getValue()));
                    }
                }
                paramsMap = map;
            }

        }

        public MockHttpServletResponse executeReturnMsg(String msg ) throws Exception{

            isJsonResult = false;

            setCookies();

            ResultActions resultAction = null;

            if(this.isMultipart){
                multiparHttps.headers(httpHeaders);
                resultAction = mvc.perform(multiparHttps);
            }else{
                https.headers(httpHeaders);
                resultAction = mvc.perform(https);
            }

            resultAction.andDo(MockMvcResultHandlers.print());
            MvcResult mvcResult = resultAction.andReturn();

            MockHttpServletResponse response = mvcResult.getResponse();

            assertTrue(response.getStatus() == 200);
            logger.debug("response.getHeader(\"Content-Type\"):"+response.getHeader("Content-Type"));
            assertTrue(response.getHeader("Content-Type").equals("application/json;charset=utf-8"));

            String resultstr = getResponseValue(response);

            if(StringUtils.isBlank(resultstr)){
                logger.error("期望返回msg提示为:"+msg+" 实际返回结果为空");
                assertTrue(false);
            }else{
                JSONObject json = JSONObject.fromObject(resultstr);
                if(json.containsKey("state") && json.containsKey("msg")){
                    if(json.getString("msg").equals(msg)){
                        logger.info("期望返回结果："+msg+" 实际返回结果："+json.getString("msg"));
                        assertTrue(true);
                    }else{
                        logger.error("期望返回msg提示为:"+msg+" 实际返回结果为:"+json.getString("msg"));
                        assertTrue(false);
                    }
                }else{
                    logger.error("期望返回msg提示为:"+msg+" 实际返回结果为:"+json);
                    assertTrue(false);
                }
            }

            resultStr = response.getContentAsString();
            isJsonResult = true;

            return response;

        }

        /**
         * 设置接口对应的详细说明
         */
        public void setDocDes(String des) {
            this.des = des;
        }

        /**
         * 创建接口文档
         *
         * @param cat_name　一级名称
         * @param des
         * @param resultParamsDes 返回值的参数说明，键值对传入
         */
        public void createDoc(String cat_name, String des, Map<String, String> resultParamsDes) {
            this.createDoc(cat_name, this.name, des, resultParamsDes);
        }

        /**
         * 创建接口文档
         *
         * @param cat_name　一级名称
         * @param cat_name_sub 二级名称
         * @param des
         * @param resultParamsDes 返回值的参数说明，键值对传入
         */
        public void createDoc(String cat_name, String cat_name_sub, String des, Map<String, String> resultParamsDes) {
            logger.debug("showDocBean:"+showDocBean.toString());
            this.des = des;
            String url = showDocBean.getSHOW_DOC_url();
            Map<String, String> params = new HashMap<String, String>();
            try {

                params.put("api_key", showDocBean.getSHOW_DOC_api_key());
                params.put("api_token", showDocBean.getSHOW_DOC_api_token());
                if (cat_name != null && !"".equals(cat_name)) {
                    params.put("cat_name", cat_name);
                }

                if (cat_name_sub != null && !"".equals(cat_name_sub)) {
                    params.put("cat_name_sub", cat_name_sub);
                }

                params.put("page_title", this.name);
                params.put("page_content", getDocContent(resultParamsDes).toString());

                List<String> keys = new ArrayList<String>(params.keySet());
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < keys.size(); i++) {
                    String key = keys.get(i);
                    String value = params.get(key) == null ? "" : params.get(key);
                    sb.append(key + "=" + URLEncoder.encode(value, "UTF-8"));
                    sb.append("&");
                }
                String result = httpUrlConnection(url, sb.toString());
                JSONObject json =  JSONObject.fromObject(result);
                if(json.containsKey("error_code")){
                    if(json.getInt("error_code") == 0){
                        logger.debug("添加接口文档成功");
                    }else{
                        logger.error("添加接口文档失败："+result);
                    }
                }else{
                    logger.error("添加接口文档失败："+result);
                }
//                logger.debug("添加接口文档：" + httpUrlConnection(url, sb.toString()));
            } catch (Exception ex) {
                logger.warn("添加接口文档出错", ex);
            }
        }

        private StringBuffer getDocContent(Map<String, String> resultParamsDes) {
            //生成页面内容
            StringBuffer str = new StringBuffer();
            str.append("  \n")
                    .append("**简要描述：**\n")
                    .append("  \n")
                    .append("- ").append(this.des == null ? this.name : this.des).append("\n")
                    .append("  \n")
                    .append("**请求URL：**  \n")
                    .append("- ").append(uri.contains(".") ? uri : uri).append("\n")
                    .append("  \n")
                    .append("**请求方式：**  \n")
                    .append("- ").append(requestType).append("\n")
                    .append("  \n")
                    .append("**请求cookies：**  \n")
                    .append("  \n")
                    .append("**请求参数：**  \n")
                    .append("  \n")
                    .append("|参数名|类型|必选|参考值|说明|  \n")
                    .append("|:----    |:---|:-----|:----- |-----   |  \n");
            if (requestParamsType == RequestParamsType.MAP) {
                if (requestParamsList != null) {
                    Map<String, String> map = new HashMap<String, String>();
                    //转换成设置到参数中
                    for (RequestParams requestParams : requestParamsList) {
                        str.append("|").append(requestParams.getName()).append("|").append(requestParams.isIsMust()).append("|").append(requestParams.value.getClass().getSimpleName())
                                .append("|").append(requestParams.getValue()).append("|").append(requestParams.getRemark()).append("\n");
                    }
                }
            } else {
                setParamsDoc(requestParamsList, str);
            }

            str.append(" **返回示例**  \n").append(" \n").append("```   \n").append(" \n").append(" \n");

            if (isJsonResult) {
                JSONObject json = JSONObject.fromObject(resultStr);
                changeJson(json, str, 0);
                str.replace(str.length() - 2, str.length() - 1, "");
                str.append("   \n").append("```  \n").append("   \n").append("   \n")
                        .append(" **返回参数说明**      \n").append("   \n").append("|参数名|类型|参考值|说明|     \n")
                        .append("|:-------|:-------|:-------|:-------|     \n");
                setResultParamsDes(json, str, resultParamsDes);
                if (resultParamsDes != null) {
                    //进行补充resultParamsDes中有但是在JSONObject中没有的参数值
                    Iterator<String> it = resultParamsDes.keySet().iterator();
                    while (it.hasNext()) {
                        String key = it.next();
                        if (!paramsJson.contains(key)) {
                            str.append("|").append(key).append("|string||").append(StringHelper.get(resultParamsDes, key)).append("|  \n");
                        }
                    }
                }
            }

//            logger.debug("stringBufferError.length()stringBufferError.length():"+stringBufferError.length());
            if(stringBufferError.length() != 0){
                str.append(" \n").append(stringBufferError);
            }

//            logger.debug("提交文档："+str);

            return str;
        }

        private List<String> paramsJson = new ArrayList<String>();

        /**
         * 设置返回值参数说明
         *
         * @param json
         * @param str
         * @param resultParamsDes
         */
        public void setResultParamsDes(JSONObject json, StringBuffer str, Map<String, String> resultParamsDes) {
            Iterator<String> it = json.keys();
            while (it.hasNext()) {
                String key = it.next();
                Object object = json.get(key);
                paramsJson.add(key);
                if (object instanceof JSONArray) {
                    JSONArray jSONArray = (JSONArray) object;
                    str.append("|").append(key).append("|object||").append(StringHelper.get(resultParamsDes, key)).append("|  \n");
                    if (jSONArray.size() > 0) {
                        setResultParamsDes(jSONArray.getJSONObject(0), str, resultParamsDes);
                    }
                } else if (object instanceof JSONObject) {
                    str.append("|").append(key).append("|object||").append(StringHelper.get(resultParamsDes, key)).append("|  \n");
                    setResultParamsDes((JSONObject) object, str, resultParamsDes);
                } else if (object instanceof String) {
                    str.append("|").append(key).append("|string|").append(String.valueOf(object)).append("|").append(StringHelper.get(resultParamsDes, key)).append("|  \n");
                } else if (object instanceof Integer) {
                    str.append("|").append(key).append("|string|").append(String.valueOf(object)).append("|").append(StringHelper.get(resultParamsDes, key)).append("|  \n");
                }
            }
        }

        private String getKb(int num) {
            String kb = "";
            for (int i = 0; i < num; i++) {
                kb += "\t";
            }
            return kb;
        }

        /**
         *
         *
         * @param json
         */
        public void changeJson(JSONObject json, StringBuffer str, int num) {
            Iterator<String> it = json.keys();
            int n = num + 1;
            logger.debug("jsonjson:"+json);
            str.append(getKb(n)).append("{\n");
            while (it.hasNext()) {
                String key = it.next();
                Object object = json.get(key);
                if (object instanceof JSONArray) {
                    str.append(getKb(n + 1)).append("\"").append(key).append("\":[\n");
                    JSONArray jsonArr = (JSONArray) object;
                    if (jsonArr.size() > 0) {
                        Object object_ = jsonArr.get(0);
                        if(object_ instanceof JSONObject){
                            changeJson(jsonArr.getJSONObject(0), str, n + 1);
                            str.append(getKb(n + 2)).append("......[\n");
                        }

                    }
                    str.replace(str.length() - 2, str.length() - 1, "");
                    str.append(getKb(n + 1)).append("],\n");
                } else if (object instanceof JSONObject) {
                    str.append(getKb(n + 1)).append("\"").append(key).append("\":{\n");
                    changeJson((JSONObject) object, str, n);
                    str.append(getKb(n + 1)).append("},\n");
                } else if (object instanceof String) {
                    str.append(getKb(n + 1)).append("\"").append(key).append("\": \"").append(String.valueOf(object)).append("\",\n");
                } else if (object instanceof Integer) {
                    str.append(getKb(n + 1)).append("\"").append(key).append("\": \"").append(String.valueOf(object)).append("\",\n");
                }
            }
            str.replace(str.length() - 2, str.length() - 1, "");
            str.append(getKb(n)).append("},\n");
        }

        /**
         * 设置参数信息
         *
         * @param requestParamsList
         * @return
         */
        private void setParamsDoc(List<RequestParams> requestParamsList, StringBuffer str) {
            if (requestParamsList != null) {
                //转换成设置到参数中
                for (RequestParams requestParams : requestParamsList) {
                    String key = requestParams.getName();
                    Object value = requestParams.getValue();
                    if (value instanceof String) {
                        str.append("|").append(requestParams.getName()).append("|").append(requestParams.value.getClass().getSimpleName()).append("|").append(requestParams.isIsMust())
                                .append("|").append(requestParams.getValue()).append("|").append(requestParams.getRemark()).append("\n");
                    } else if ((value instanceof List)) {


                        List<?> lists = (List<?>)value;

                        for(Object params_ :lists){
                            if(params_ instanceof RequestParams){
                                try {
                                    List<RequestParams> list = (List<RequestParams>) value;
                                    str.append("|").append(requestParams.getName()).append("|").append("object").append("|").append(requestParams.isIsMust())
                                            .append("|").append("").append("|").append(requestParams.getRemark()).append("\n");
                                    setParamsDoc(list, str);
                                } catch (Exception e) {
                                    try {
                                        List<ArrayList<RequestParams>> list = (List<ArrayList<RequestParams>>) value;
                                        for (List<RequestParams> param : list) {
                                            setParamsDoc(param, str);
                                        }
                                    } catch (Exception e1) {
                                        logger.warn("参数类型转换出错:", e1);
                                    }
                                }
                            }else if(params_ instanceof String){
                                str.append("|").append(requestParams.getName()).append("|").append(requestParams.value.getClass().getSimpleName()).append("|").append(requestParams.isIsMust())
                                        .append("|").append(requestParams.getValue()).append("|").append(requestParams.getRemark()).append("\n");
                            }else if(params_ instanceof Integer){
                                str.append("|").append(requestParams.getName()).append("|").append(requestParams.value.getClass().getSimpleName()).append("|").append(requestParams.isIsMust())
                                        .append("|").append(requestParams.getValue()).append("|").append(requestParams.getRemark()).append("\n");
                            }else if(params_ instanceof Map){
                                str.append("|").append(requestParams.getName()).append("|").append(requestParams.value.getClass().getSimpleName()).append("|").append(requestParams.isIsMust())
                                        .append("|").append(requestParams.getValue()).append("|").append(requestParams.getRemark()).append("\n");
                            }
                        }


                    } else {
                        logger.error("未知的参数值");
                    }
                }
            }
        }
    }

    private String httpUrlConnection(String urlPath, String param) {
        try {
            //建立连接
            URL url = new URL(urlPath);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            //设置参数
            httpConn.setDoOutput(true);   //需要输出
            httpConn.setDoInput(true);   //需要输入
            httpConn.setUseCaches(false);  //不允许缓存
            httpConn.setRequestMethod("POST");   //设置POST方式连接
            //设置请求属性
            httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            httpConn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
            httpConn.setRequestProperty("Charset", "UTF-8");
            //连接,也可以不用明文connect，使用下面的httpConn.getOutputStream()会自动connect
            httpConn.connect();
            //建立输入流，向指向的URL传入参数
            DataOutputStream dos = new DataOutputStream(httpConn.getOutputStream());
            dos.writeBytes(param);
            dos.flush();
            dos.close();
            //获得响应状态
            int resultCode = httpConn.getResponseCode();
            if (HttpURLConnection.HTTP_OK == resultCode) {
                StringBuffer sb = new StringBuffer();
                String readLine = new String();
                BufferedReader responseReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "UTF-8"));
                while ((readLine = responseReader.readLine()) != null) {
                    sb.append(readLine).append("\n");
                }
                responseReader.close();
                return sb.toString();
            }
            logger.debug("文档添加失败："+resultCode);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }

    /**
     * 上传表信息
     *
     * @param projectName 项目名称
     * @param tableName 表名，多个使用英文,隔开　模糊匹配使用%如两边模糊查询%t_sss%
     */
    public void uploadTableDoc(String projectName, String tableName) {
//        MySqlMap mySqlMap = new MySqlMap();
//        String sql = "SELECT * FROM information_schema.TABLES a \n"
//                + "  where a.TABLE_SCHEMA = database() and ( ";
//        StringTokenizer sta = new StringTokenizer(tableName, ",");
//        int i = 0;
//        while (sta.hasMoreTokens()) {
//            String val = sta.nextToken();
//            sql += " a.TABLE_NAME like :key" + i + " or";
//            mySqlMap.put("key" + i, val);
//            i++;
//        }
//        sql = sql.substring(0, sql.length() - 2) + ")";
//        List<Map<String, Object>> tableList = db.queryForList(sql, mySqlMap);
//        logger.debug("执行ｓｑｌ：" + tableList);
//        StringBuffer str = new StringBuffer();
//        for (int j = 0; j < tableList.size(); j++) {
//            Map<String, Object> map = tableList.get(j);
//            String TABLE_SCHEMA = StringHelper.get(map, "TABLE_SCHEMA");
//            String table_name = StringHelper.get(map, "TABLE_NAME");
//            String table_con = StringHelper.get(map, "TABLE_COMMENT");
//
//            if(table_name.endsWith("_his")){
//                continue;
//            }
//
//            //查询此表下面所有的字段
//            sql = "select * FROM information_schema.COLUMNS a \n"
//                    + "    where a.TABLE_SCHEMA = database() and a.TABLE_NAME = :table_name";
//            mySqlMap.put("table_name", table_name);
//            List<Map<String, Object>> tableColumnsList = db.queryForList(sql, mySqlMap);
//            StringBuffer strColumns = new StringBuffer();
//            strColumns.append("- #### 表名称：" + table_name + "\n")
//                    .append("##### 表说明：" + table_con + "\n\n").append("|字段|类型|空|键值类型|注释|\n").append("|:----    |:-------    |:--- |------      |\n");
//            for (int u = 0; u < tableColumnsList.size(); u++) {
//                Map<String, Object> mapColumns = tableColumnsList.get(u);
//                String COLUMN_NAME = StringHelper.get(mapColumns, "COLUMN_NAME");
//                String IS_NULLABLE = StringHelper.get(mapColumns, "IS_NULLABLE");
//                String COLUMN_TYPE = StringHelper.get(mapColumns, "COLUMN_TYPE");
//                String COLUMN_COMMENT = StringHelper.get(mapColumns, "COLUMN_COMMENT");
//
//                strColumns.append("|" + COLUMN_NAME + "	  |" + COLUMN_TYPE + "     |" + IS_NULLABLE + "|	|" + COLUMN_COMMENT + "	 | \n");
//            }
//            str.append(strColumns);
//
////            String url = "http://doc.zexingwei.com/server/index.php?s=/api/item/updateByApi";
////            String url = "http://182.254.209.240:8028/server/index.php?s=/api/item/updateByApi";
//            String url = "http://192.168.90.198/showdoc-master/server/index.php?s=/api/item/updateByApi";
//            Map<String, String> params = new HashMap<String, String>();
//            try {
////                params.put("api_key", "8ee4b896190a40515c8d154965d6aaa21391692549");
////                params.put("api_token", "d109fd24320f428795e7febe6778b4eb894658075");
//
//                params.put("api_key", "7ea36480c97421f722d89008ca7b386b487110605");
//                params.put("api_token", "bc89bf793c822f893fe90ef68ae4702c1334725373");
//
//                params.put("cat_name", projectName);
//                params.put("cat_name_sub", TABLE_SCHEMA);
//                params.put("page_title", table_name);
//                params.put("page_content", strColumns.toString());
//
//                List<String> keys = new ArrayList<String>(params.keySet());
//                StringBuilder sb = new StringBuilder();
//                for (int o = 0; o < keys.size(); o++) {
//                    String key = keys.get(o);
//                    String value = params.get(key) == null ? "" : params.get(key);
//                    sb.append(key + "=" + URLEncoder.encode(value, "UTF-8"));
//                    sb.append("&");
//                }
//                JSONObject json = JSONObject.fromObject(httpUrlConnection(url, sb.toString()));
//                if (json.containsKey("error_code")) {
//                    if (json.getInt("error_code") == 0) {
//                        logger.debug("添加接口文档成功：" + table_name);
//                    } else {
//                        logger.debug("添加接口文档成功：" + table_name);
//                    }
//                } else {
//                    logger.error("添加接口文档失败：" + table_name);
//                }
//            } catch (Exception ex) {
//                logger.warn("添加接口文档出错", ex);
//            }
//        }
    }

}
